package com.tiger.admin.http.statistics;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tiger.admin.Db;
import com.tiger.db.entity.*;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class StatisticsService {
    private final Db db;

    public StatisticsService(Db db) {
        this.db = db;
    }

    public List<AppCategory> topCategory() {
        return db.appCategory.list(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getId, AppCategory::getName).eq(AppCategory::getTopId, 0).eq(AppCategory::isEnable, true));
    }

    //分类下的app总数
    public long appCountOfCategory(Integer categoryId) {
        LambdaQueryWrapper<App> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(App::getTaskApp, false);
        if(categoryId != 0) {
            AppCategory category = db.appCategory.getOne(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getName, AppCategory::getId, AppCategory::getTopId).eq(AppCategory::getId, categoryId));


            if(category != null && category.getTopId() == 0) {
                List<AppCategory> rows = db.appCategory.list(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getId).eq(AppCategory::getTopId, categoryId));
                List<Integer> ids = rows.stream().map(AppCategory::getId).collect(Collectors.toList());
                ids.add(categoryId);
                wrapper.in(App::getCategory, ids);
            }else {
                return 0;
            }
        }

        return db.app.count(wrapper);
    }

    //访客人数
    public long uniqueVisitors(Integer categoryId) {
        long count = 0;
        LambdaQueryWrapper<AppCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(AppCategory::getUniqueVisitors);
        if(categoryId == 0) {
            wrapper.eq(AppCategory::getTopId, 0);
            List<AppCategory> rows = db.appCategory.list(wrapper);
            for(AppCategory item:rows) {
                count += item.getUniqueVisitors();
            }
        }else {
            wrapper.eq(AppCategory::getId, categoryId);
            AppCategory category = db.appCategory.getOne(wrapper);
            count = category.getUniqueVisitors();
        }


        return count;
    }

    //访问次数
    public long visitTimes(Integer categoryId) {
        long count = 0;
        LambdaQueryWrapper<AppCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(AppCategory::getVisitTimes);
        if(categoryId == 0) {
            wrapper.eq(AppCategory::getTopId, 0);
            List<AppCategory> rows = db.appCategory.list(wrapper);
            for(AppCategory item:rows) {
                count += item.getVisitTimes();
            }
        }else {
            wrapper.eq(AppCategory::getId, categoryId);
            AppCategory category = db.appCategory.getOne(wrapper);
            count = category.getVisitTimes();
        }


        return count;
    }


    public List<HashMap<String, Object>> categoryAppCount() {
        List<HashMap<String, Object>> res = new ArrayList<>();
        List<AppCategory> categories = db.appCategory.list(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getName, AppCategory::getId).eq(AppCategory::getTopId, 0));
        for(AppCategory item:categories) {
            HashMap<String, Object> row = new HashMap<>();
            row.put("name", item.getName());
            row.put("count", appCountOfCategory(item.getId()));

            res.add(row);
        }

        return res;
    }

    public List<HashMap<String, Object>> rankVisitTimesByMonth(String month, int size) {
        List<HashMap<String, Object>> res = new ArrayList<>();

        LambdaQueryWrapper<AppVisitMonthStatistic> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppVisitMonthStatistic::getMonth, month);
        wrapper.orderByDesc(AppVisitMonthStatistic::getVisitTimes);
        wrapper.last("limit " + size);

        List<AppVisitMonthStatistic> rows = db.appVisitMonthStatistic.list(wrapper);

        if(!rows.isEmpty()) {
            List<Long> appIds = rows.stream().map(AppVisitMonthStatistic::getAppId).collect(Collectors.toList());
            List<App> apps = db.app.list(new LambdaQueryWrapper<App>().select(App::getName, App::getId).in(App::getId, appIds));

            for(AppVisitMonthStatistic item : rows) {
                Optional<App> app = apps.stream() // 将List转换为流
                        .filter(v -> Objects.equals(v.getId(), item.getAppId())).findFirst();


                if(app.isPresent()) {
                    HashMap<String, Object> r = new HashMap<>();
                    r.put("name", app.get().getName());
                    r.put("visitTimes", item.getVisitTimes());

                    res.add(r);
                }





            }

        }

        return res;
    }

    public List<HashMap<String, Object>> rankVisitTimesByYear(String year, int size) {
        List<HashMap<String, Object>> res = new ArrayList<>();

        LambdaQueryWrapper<AppVisitYearStatistic> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppVisitYearStatistic::getYear, year);
        wrapper.orderByDesc(AppVisitYearStatistic::getVisitTimes);
        wrapper.last("limit " + size);

        List<AppVisitYearStatistic> rows = db.appVisitYearStatistic.list(wrapper);

        if(!rows.isEmpty()) {
            List<Long> appIds = rows.stream().map(AppVisitYearStatistic::getAppId).collect(Collectors.toList());
            List<App> apps = db.app.list(new LambdaQueryWrapper<App>().select(App::getName, App::getId).in(App::getId, appIds));

            for(AppVisitYearStatistic item : rows) {
                Optional<App> app = apps.stream() // 将List转换为流
                        .filter(v -> Objects.equals(v.getId(), item.getAppId())).findFirst();

                if(app.isPresent()) {
                    HashMap<String, Object> r = new HashMap<>();
                    r.put("name", app.get().getName());
                    r.put("visitTimes", item.getVisitTimes());
                    res.add(r);
                }



            }

        }

        return res;
    }
}
